package com.yonyougov.devops.cruxcisupport;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyougov.devops.cruxcisupport.component.UserStore;
import com.yonyougov.devops.cruxcisupport.constvar.DevOpsErrorCode;
import com.yonyougov.devops.cruxcisupport.user.vo.JwtUser;
import com.yonyougov.devops.cruxcisupport.util.JWTTokenUtil;
import com.yonyougov.devops.fwc.api.dto.BaseResponseDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    private final UserStore userStore;
    public static final String LOGIN_KEY = "yonyougov";
    public static String[] ignoreUrls = new String[]{"^[http,https].*login.*", "^[http,https].*/u/add.*",
            "^[http,https].*/u/update.*","^[http,https].*/env/e/names.*",
            "^[http,https].*swagger.*", "^[http,https].*deployFile.*", "^[http,https].*configMap.*",
            "^[http,https].*downloadall.*", "^[http,https].*download",
            "^[http,https].*cluster.*", "^[http,https].*appenvport/aep/serverInfo", "^[http,https].*/server/u/status",
            "^[http,https].*/env/query", "^[http,https].*/encrypt", "^[http,https].*/decrypt"
            //,"^[http,https].*/harbor.*"
    };
    private ObjectMapper objectMapper;

    public LoginInterceptor(UserStore userStore, ObjectMapper objectMapper) {
        this.userStore = userStore;
        this.objectMapper = objectMapper;
    }

    private boolean skip(HttpServletRequest request) {
        String url = request.getRequestURL().toString();
        for (String ignoreUrl : ignoreUrls) {
            if (url.matches(ignoreUrl)) {
                log.debug("跳过登录验证:{}", url);
                return true;
            }
        }
        return false;
    }

    private String getToken(HttpServletRequest request) {
        String method = request.getMethod();
        if (HttpMethod.GET.name().equals(method)) {
            String token = request.getParameter("token");
            return StringUtils.isBlank(token) ? request.getHeader("token") : token;
        }
        return request.getHeader("token");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getMethod().equals(HttpMethod.OPTIONS.name())) {
            return true;
        }
        log.debug("开始访问接口:{}", request.getRequestURI());
        if (skip(request)) {
            log.debug("接口:{}不需要认证跳过", request.getRequestURI());
            return true;
        }
        String token = getToken(request);
//        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {
            response.setStatus(401);
            log.error("header没有token");
            BaseResponseDto dto = BaseResponseDto.getFailInstance(DevOpsErrorCode.AUTH_NO_TOKEN);
            response.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            objectMapper.writeValue(response.getWriter(), dto);
            return false;
        }
        JwtUser jwtUser = JWTTokenUtil.parseJWT(token, LOGIN_KEY);
        if (jwtUser == null) {
            response.setStatus(403);
            log.error("token无效需要重新登录");
            BaseResponseDto dto = BaseResponseDto.getFailInstance(DevOpsErrorCode.AUTH_TOKEN_INVALID);
            response.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding("UTF-8");
            objectMapper.writeValue(response.getWriter(), dto);
            return false;
        }
        log.debug("jwt 解析成功....");
        userStore.setCurrentJwtUser(jwtUser);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        userStore.removeCurrentUser();
    }
}
